import { Loading } from './../../Loading';
import { _decorator, assert, assetManager, Canvas, Component, director, game, HorizontalTextAlignment, instantiate, log, Node, Prefab, Widget } from 'cc';
import { Layer } from './Layer';
import { ViewLayerDefine } from './VewLayerDefine';
import { BaseView } from './BaseView';
import { LoadingLayer } from './layers/LoadingLayer';
import AssetMgr from '../asset/AssetMgr';
import { GameLayer } from './layers/GameLayer';
import { MainLayer } from './layers/MainLayer';
import { PopLayer } from './layers/PopLayer';
import { TipsLayer } from './layers/TipsLayer';
import { TopLayer } from './layers/TopLayer';
import ViewDefine from '../../game/ui/ViewDefine';
import { ResourceNames } from '../../game/constant/CommonConstant';
const { ccclass, property } = _decorator;

//TODO 切换场景时，各个层节点怎么管理呢,
//方案1：切换场景，新场景重新初始化UIRoot和
//方案2：UImanager绑定一个单独的UICanvas节点，换场景不销毁，UICanvas单独定一个层，UICanvas的相机只渲染此Canvas,调节相机优先级改变渲染顺序
@ccclass('UIMgr')
export class UIMgr {


    private static _instance: UIMgr;
    /**
     * 游戏层，主要显示游戏场景中的UI，比如伤害飘字，敌人血条，场景指引，状态图标等,这个我们管理器一般不处理
     */
    private gameLayer: Layer;
    /**
     * 主UI层，主要显示游戏UI最底层界面，比如Loading界面，游戏主界面，战斗UI界面，这些界面排他，且这个层只能有一个界面显示
     */
    private mainLayer: Layer;
    /**
     * 弹出层，用于显示功能界面，比如点击主界面的功能按钮，弹出功能界面，此层是栈结构，可以被后续的UI界面覆盖
     * 如果这个界面是排他的，则显示前会关闭其他所有的弹出界面
     */
    private popLayer: Layer;
    /**
     * 公告等弹出层
     */
    private topLayer: Layer;
    /**
     * loading层，用于显示游戏加载界面，显示这个界面时，会关闭其他所有的界面，除了tipsLayer
     */
    private loadingLayer: Layer;
    /**
     * 提示层，用于显示一些提示信息，比如跑马灯，错误提示，警告等，此层是栈结构，只显示跑马灯和飘字提示，飘字提示
     * 渲染在拍马灯后
     */
    private tipsLayer: Layer;

    private views: Map<string, BaseView> = new Map();
    private uiRootNode: Node = null;
    public canvas: Canvas;
    public canvasNode: Node;
    public static get Ins() {
        if (!UIMgr._instance) {
            UIMgr._instance = new UIMgr();
        }
        return UIMgr._instance;
    }

    public init(canvas: Canvas) {
        //TODO 优化：canvas和canvas的渲染相机代码创建
        if(canvas==null){
            console.error("ui manager init canvas is null");
            
        }
        this.canvas = canvas;
        this.canvas.node.setPosition(0, 0);
        this.canvasNode = this.canvas.node;
        this.createLayerNode();
        director.addPersistRootNode(this.canvasNode);
        console.log('ui manager init');
    }

    destroyed(): void {
        console.log('ui manager destroyed');
    }

    createLayerNode() {
        this.uiRootNode  = new Node("UIRoot");
        this.addWidgetFullParent(this.uiRootNode)
        this.uiRootNode.setParent(this.canvas.node);


        this.gameLayer = this.addLayer(ViewLayerDefine.Game);
        this.mainLayer = this.addLayer(ViewLayerDefine.Main);
        this.popLayer = this.addLayer(ViewLayerDefine.Pop);
        this.popLayer = this.addLayer(ViewLayerDefine.Top);
        this.loadingLayer = this.addLayer(ViewLayerDefine.Laoding);
        this.tipsLayer = this.addLayer(ViewLayerDefine.Tips);

    }

    private addWidgetFullParent(node: Node){
        let widget = node.addComponent(Widget)
        widget.isAlignLeft = true;
        widget.left = 0;
        widget.isAlignRight = true;
        widget.right = 0;
        widget.isAlignTop = true;
        widget.top = 0;
        widget.isAlignBottom = true;
        widget.bottom = 0;
        widget.isAlignLeft = true;
    }

    private addLayer(layer: ViewLayerDefine) {
        let layerNode = new Node(layer);
        this.addWidgetFullParent(layerNode)
        layerNode.setParent(this.uiRootNode);
        let layerComp;
        switch (layer) {
            case ViewLayerDefine.Game:
                layerComp = layerNode.addComponent(GameLayer);
                break;
            case ViewLayerDefine.Main:
                layerComp = layerNode.addComponent(MainLayer);
                break;
            case ViewLayerDefine.Pop:
                layerComp = layerNode.addComponent(PopLayer);
                break;
            case ViewLayerDefine.Top:
                layerComp = layerNode.addComponent(TopLayer);
                break;
            case ViewLayerDefine.Laoding:
                layerComp = layerNode.addComponent(LoadingLayer);
                break;
            case ViewLayerDefine.Tips:
                layerComp = layerNode.addComponent(TipsLayer);
                break;
        }
        return layerComp;
    }

    start() {

    }

    public async show(name: string,isLoading = false) {
        let view = this.views.get(name)
        if (view) {
            this.showViewByScript(view);
            return
        }
        //加载资源
        let uiViewPrefab:Prefab;
        if(name==ViewDefine.LoadingView){
            uiViewPrefab = await AssetMgr.Ins.loadPrefab(ResourceNames.StartResources,name);
        }else{
            uiViewPrefab = await AssetMgr.Ins.loadPrefab(ResourceNames.UIResources,name);
        }
        if(uiViewPrefab==null){
            console.error(`${name} ui prefab not found`);
            return;
        }

        let viewNode = instantiate(uiViewPrefab);
        viewNode.active = false;
        let viewScript = viewNode.addComponent(uiViewPrefab.name) as BaseView;
        viewScript.viewName = uiViewPrefab.name;
        this.views.set(name, viewScript);
        this.showViewByScript(viewScript)
    }

    private showViewByScript(view:BaseView){
        switch (view.layer) {
            case ViewLayerDefine.Game:
               console.log('GameLayer show:'+view.viewName);
                this.gameLayer.show(view);
                break;
            case ViewLayerDefine.Main:
                console.log('MainLayer show:'+view.viewName);
                this.mainLayer.show(view);
                break;
            case ViewLayerDefine.Pop:
                console.log('PopLayer show:'+view.viewName);
                this.popLayer.show(view);
                break;
            case ViewLayerDefine.Top:
                console.log('TopLayer show:'+view.viewName);
                this.topLayer.show(view);
                break;
            case ViewLayerDefine.Laoding:
                console.log('LoadingLayer show:'+view.viewName);
                this.loadingLayer.show(view);
                break;
            case ViewLayerDefine.Tips:
                console.log('TipsLayer show:'+view.viewName);
                this.tipsLayer.show(view);
                break;
        }
    }

    public async hide(name: string) {
        let view = this.views.get(name)
        if (view) {
            this.hideViewByScript(view);
            return
        }
        console.error("未找到要关闭的UI："+name);
    
    }

    private hideViewByScript(view:BaseView){
        switch (view.layer) {
            case ViewLayerDefine.Game:
                console.log('GameLayer hide:'+view.viewName);
                this.gameLayer.hide(view);
                break;
            case ViewLayerDefine.Main:
                console.log('MainLayer hide:'+view.viewName);
                this.mainLayer.hide(view);
                break;
            case ViewLayerDefine.Pop:
                console.log('PopLayer hide:'+view.viewName);
                this.popLayer.hide(view);
                break;
            case ViewLayerDefine.Top:
                console.log('TopLayer hide:'+view.viewName);
                this.topLayer.hide(view);
                break;
            case ViewLayerDefine.Laoding:
                console.log('LaodingLayer hide:'+view.viewName);
                this.loadingLayer.hide(view);
                break;
            case ViewLayerDefine.Tips:
                console.log('TipsLayer hide:'+view.viewName);
                this.tipsLayer.hide(view);
                break;
        }
    }

    public hideLayer(layer:ViewLayerDefine) {
        switch (layer) {
            case ViewLayerDefine.Game:
                this.gameLayer.hideAll();
                break;
            case ViewLayerDefine.Main:
                this.mainLayer.hideAll();
                break;
            case ViewLayerDefine.Pop:
                this.popLayer.hideAll();
                break;
            case ViewLayerDefine.Top:
                this.topLayer.hideAll();
                break;
            case ViewLayerDefine.Laoding:
                this.loadingLayer.hideAll();
                break;
            case ViewLayerDefine.Tips:
                this.tipsLayer.hideAll();
                break;
        }
    }
}


